<template>
  <div>
    <!--系统图列表区-->
    <SysView v-show="!ifEditStatus" :edit="ifEditStatus" @tell-edit="tellEdit" ref="listPanel"></SysView>
    <!--系统图编辑区-->
    <div class="mainBgg" v-show="ifEditStatus">
      <div style="flex: 10;">
        <div class="editPanel">
          <Row :gutter="10">
            <Col span="20">
              <ButtonGroup>
                <Button type="primary" icon="md-return-left" @click="changePanel">返回</Button>
              </ButtonGroup>
              <RadioGroup v-model="model" type="button" @on-change="radioChage">
                <Radio label="编辑"></Radio>
                <Radio label="只读"></Radio>
                <Radio label="连线"></Radio>
              </RadioGroup>
              <!--<Select v-model="editLineType" style="width: 15%;" :disabled="model !='连线'" @on-change="lineTypeChange">
                <Option value="Q.Consts.EDGE_TYPE_VERTICAL_HORIZONTAL">单直角</Option>
                <Option value="Q.Consts.EDGE_TYPE_ORTHOGONAL_HORIZONTAL">双直角</Option>
                <Option value="Q.Consts.EDGE_TYPE_EXTEND_TOP">长短双直角（顶部）</Option>
                <Option value="Q.Consts.EDGE_TYPE_EXTEND_BOTTOM">长短双直角（底部）</Option>
                <Option value="Q.Consts.EDGE_TYPE_EXTEND_LEFT">长短双直角（左部）</Option>
                <Option value="Q.Consts.EDGE_TYPE_EXTEND_RIGHT">长短双直角（右部）</Option>
                <Option value="Q.Consts.EDGE_TYPE_ELBOW_HORIZONTAL">双160°角</Option>
                <Option value="Q.Consts.EDGE_TYPE_ZIGZAG">中间折线</Option>
                <Option value="Q.Consts.EDGE_TYPE_EXTEND_TOP">顶部双直角</Option>
                <Option value="Q.Consts.EDGE_TYPE_EXTEND_BOTTOM">底部双直角</Option>
                <Option value="Q.Consts.EDGE_TYPE_EXTEND_RIGHT">右部双直角</Option>
                <Option value="Q.Consts.EDGE_TYPE_EXTEND_LEFT">左部双直角</Option>
              </Select>-->
              <ButtonGroup>
                <!--<Button type="primary" icon="ios-crop" @click="exportImage">导出图片</Button>-->
                <!--<Button type="primary" icon="ios-color-filter-outline" @click="exportJsons">导出json数据</Button>-->
                <Button type="primary" @click="switches.jsonModal = true" :disabled="curObj.id !== undefined">导入</Button>
                <Button type="primary" @click="switches.drawer = true">导出</Button>
                <Button type="primary" @click="xAline">水平对齐</Button>
                <Button type="primary" @click="yAline">垂直对齐</Button>
                <Button type="primary" @click="wo">自码</Button>
                <Button type="info" @click="doFlow">流动</Button>
                <Button type="info" @click="stopFlow">停流</Button>
                <Button type="primary" @click="autoFit">适应</Button>
              </ButtonGroup>
              <ButtonGroup>
                <Button type="error" @click="emptyPanel" :disabled="curObj.id !== undefined">
                  清空
                </Button>
                <Button type="error" :loading="switches.delImgStatus" @click="delPic" :disabled="curObj.id ===undefined">
                  删除
                </Button>
              </ButtonGroup>
            </Col>
            <Col span="2">
              <div class="ddz21">
                <div class="ddz3">
                  <Select v-model="curObj.space">
                    <Option v-for="item in spaceList2" :value="item.label" :key="item.value">{{ item.label }}</Option>
                  </Select>
                </div>
              </div>
            </Col>
            <Col span="2">
              <!--能源类型 -->
              <div class="ddz21">
                <div class="ddz3">
                  <Select v-model="curObj.energy">
                    <Option v-for="item in energyList" :value="item.label" :key="item.index">{{ item.label }}</Option>
                  </Select>
                </div>
              </div>
            </Col>
          </Row>
          <div style="position: relative;margin-top: 5px;">
            <div class="cann" id="canvasasd"/>
          </div>
          <!--7878787 // mm -->
          <Drawer title="设置连线样式" :closable="false" width="420" v-model="setttingModalLine"
                  @on-visible-change="modalVisible">
            <Form :model="tempSetting" :label-width="80">
              <FormItem label="线条标签">
                <Input v-model="tempSetting.label" placeholder="线条标签"></Input>
              </FormItem>
              <FormItem label="线条ID">
                <Input v-model="tempSetting.did" placeholder="线条ID"></Input>
              </FormItem>
              <FormItem label="线条宽度">
                <InputNumber :max="20" :min="1" v-model="tempSetting.width"></InputNumber>
              </FormItem>
              <FormItem label="线条颜色">
                <!--<Input v-model="tempSetting.color" placeholder="颜色代码"></Input>-->
                <ColorPicker v-model="tempSetting.color" recommend/>
              </FormItem>
              <FormItem label="流动颜色">
                <ColorPicker v-model="tempSetting.flowColor" recommend/>
              </FormItem>
              <FormItem label="线条层级">
                <InputNumber v-model="tempSetting.zindex"></InputNumber>
              </FormItem>
              <FormItem>
                <Button type="primary" @click="okLine" style="width: 150px;float: right;margin-right: 10px;">修改</Button>
              </FormItem>
            </Form>
          </Drawer>
          <Drawer title="设置图元样式" :closable="false" width="420" v-model="setttingModalNode"
                  @on-visible-change="modalVisible">
            <Form :model="tempSetting" :label-width="100">
              <FormItem label="图元名称">
                <Input v-model="tempSetting.label" placeholder="图元名称"></Input>
              </FormItem>
              <FormItem label="ID">
                <Input v-model="tempSetting.did" placeholder="关联设备ID（组态）"></Input>
              </FormItem>
              <FormItem label="关联设备ID">
                <Input v-model="tempSetting.devId" placeholder="关联设备ID(设备id)"></Input>
              </FormItem>
              <FormItem label="设备协议">
                <Input v-model="tempSetting.prol" placeholder="设备协议（控制区别用）"></Input>
              </FormItem>
              <FormItem label="图元大小">
                <InputNumber :min="1" v-model="tempSetting.size"></InputNumber>
              </FormItem>
              <FormItem label="图元层级">
                <InputNumber v-model="tempSetting.zindex"></InputNumber>
              </FormItem>
              <FormItem label="显示图元名称">
                <RadioGroup v-model="tempSetting.showName">
                  <Radio label="true" :true-value="true">显示</Radio>
                  <Radio label="false" :false-value="false">隐藏</Radio>
                </RadioGroup>
              </FormItem>
              <FormItem label="关联线条">
                <Input v-model="tempSetting.lines" placeholder="对应的控制线条ID，逗号隔开"></Input>
              </FormItem>
              <FormItem>
                <Button type="primary" @click="okNode" style="width: 150px;float: right;margin-right: 10px;">修改</Button>
              </FormItem>
            </Form>
          </Drawer>
          <Modal :closable="false" :mask="true" @on-visible-change="modalVisible"
                 v-model="switches.jsonModal "
                 title="导入json数据"
                 @on-ok="importJsons"
                 @on-cancel="cancel">
            <textarea rows="15" v-model="doneJson" style="width: 100%;" placeholder="请输入有效的布局json数据..."></textarea>
          </Modal>
        </div>
      </div>
      <div style="flex: 2;">
        <Row class="fatherToolBar" :gutter="10">
          <Col span="16">
            <Input placeholder="系统图名称..." v-model="curObj.name" style="margin-left: 5px;"></Input>
          </Col>
          <Col span="8" style="text-align: right;">
            <Button type="primary" icon="md-checkmark" :loading="switches.savingImgStatus" @click="saveData"
                    style="margin-left: 10px;">{{this.curObj.id ? '保存编辑': '保存新增' }}
            </Button>
          </Col>
        </Row>
        <Row class="devBBT1">代码生成模块</Row>
        <Row class="devBB" :gutter="5">
          <!--<Col span="7" v-for="(dd, index) in devs" :key="dd.id" @dblclick.native="addToPool(index)" class="devBg"
               v-show="dd.ifShow">
            <DevCard :dev="dd"></DevCard>
          </Col>
            <Spin size="large" fix v-if="switches.loadDevStatus"></Spin>-->
        </Row>
        <Row class="devBBC">
          <Row class="devBBT">组图图标</Row>
          <Col span="7" v-for="(ico, index) in selectionIcons" :key="ico" @click.native="addToPool2(ico)"
               class="devBg">
            <SvgCard :name="ico"></SvgCard>
          </Col>
        </Row>
        <Row class="devBBCD">
          <Row class="devBBT">代码生成模块</Row>
          <div style="margin-top: 5px">
            <Button type="primary" ghost @click="makeTextNode">文字模块</Button>
            <Button type="primary" ghost @click="makeBusLine">总线线条</Button>
          </div>
        </Row>
      </div>
      <Drawer :closable="false" width="640" v-model="switches.drawer" style="padding: 5px;"
              @on-visible-change="drawerChange">
        <textarea name="jsoss" id="json" style="width: 100%;height: 100%;" v-model="expertEditJson"></textarea>
      </Drawer>
      <Drawer :closable="false" width="400" v-model="switches.textDrawer" style="padding: 5px;"
              @on-visible-change="textDrawerChange" title="配置文本信息">
        <Form :model="tempSetting" :label-width="100">
          <FormItem label="文本名称">
            <Input v-model="tempSetting.label" placeholder="图元名称"></Input>
          </FormItem>
          <FormItem label="图元ID">
            <Input v-model="tempSetting.did" placeholder="关联设备ID（组态）"></Input>
          </FormItem>
          <FormItem label="关联设备ID">
            <Input v-model="tempSetting.devId" placeholder="关联设备ID(设备id)"></Input>
          </FormItem>
          <FormItem label="设备协议">
            <Input v-model="tempSetting.prol" placeholder="设备协议（控制区别用）"></Input>
          </FormItem>
          <FormItem label="文字大小">
            <InputNumber :min="15" v-model="tempSetting.textSize"></InputNumber>
          </FormItem>
          <FormItem label="文字颜色">
            <ColorPicker v-model="tempSetting.textColors" recommend/>
          </FormItem>
          <FormItem label="背景颜色">
            <ColorPicker v-model="tempSetting.textBgColor" recommend/>
          </FormItem>
          <FormItem label="边框颜色">
            <ColorPicker v-model="tempSetting.textBorderColor" recommend/>
          </FormItem>
          <!--       <FormItem label="图元大小">
                   <InputNumber :min="1" v-model="tempSetting.size"></InputNumber>
                 </FormItem>-->
          <FormItem label="图元层级">
            <InputNumber v-model="tempSetting.zindex"></InputNumber>
          </FormItem>
        </Form>
        <Row style="text-align: right;padding-right: 10px;">
          <Button type="primary" @click="okText">修改</Button>
        </Row>
      </Drawer>
    </div>
  </div>
</template>
<script>
  import SysView from './SysView'
  import DevCard from './DevCard'
  import SvgCard from './SvgCard'
  import {FlowingSupport} from '../../../static/qunee/flowPrototype'
  // import {TableUI} from '../../../static/qunee/tableUI'
  export default {
    name: 'SysPic',
    components: {SysView, DevCard, SvgCard},
    mounted: function () {
      this.getSpaceList()
      this.addProptype()
      this.generateBg()
    },
    data () {
      return {
        graph: null,
        flowObj: null,
        CopyElements: null,
        ifEditStatus: false,
        doneJson: '', // 导入json数据
        model: '编辑', // 默认的 系统图 编辑 模式
        editLineType: Q.Consts.EDGE_TYPE_VERTICAL_HORIZONTAL,
        factName: [], // 设备刷选 空间选择存储
        expertEditJson: '',
        spaceList: [],
        selectionIcons: Q.getAllImages().filter(item => item !== 'lamp'),
        devs: [],
        inPool: [], // 保存已经关联在 系统图中的 数据 id 或 obj
        outPool: [], // 保存未关联在 系统图中的 数据 id 或 obj
        picPool: [], // 已经在或 添加在系统图中的  数据 id 或 obj
        switches: {
          loadDevStatus: false, // 加载设备状态
          delImgStatus: false, // 删除系统图状态
          drawer: false, // 删除系统图状态
          textDrawer: false, // 删除系统图状态
          savingImgStatus: false, // 保存系统图 状态
          jsonModal: false //  导入json数据的模态框
        },
        spaceList2: [],
        energyList: [
          {
            label: '电',
            index: 1
          },
          {
            label: '水',
            index: 2
          },
          {
            label: '冷量',
            index: 3
          },
          {
            label: '燃气',
            index: 4
          },
          {
            label: '压缩空气',
            index: 5
          }
        ],
        tempSetting: {
          color: '#333333',
          flowColor: '',
          textColors: '',
          textBgColor: '',
          textBorderColor: ''
        }, // 临时存储 编辑节点的 设置项
        edittingNode: null, // 当前编辑的节点 或者 线条
        curObj: {},
        setttingModalLine: false,
        setttingModalNode: false,
        events: {
          oncontextmenu: (evt, graph) => {
            Q.log(evt)
          },
          ondblclick: (evt, graph) => {
            this.edittingNode = null
            if (!evt.getData()) {
              return
            }
            this.edittingNode = evt.getData()
            console.log('双击Node数据', evt.getData())
            this.edittingNode = evt.getData()
            this.tempSetting.label = evt.getData().name === undefined ? '' : evt.getData().name
            this.tempSetting.zindex = evt.getData().zIndex === undefined ? 1 : evt.getData().zIndex
            this.tempSetting.did = (evt.getData().get('did') === undefined ? ' ' : evt.getData().get('did'))
            this.tempSetting.prol = (evt.getData().get('prol') === undefined ? ' ' : evt.getData().get('prol'))
            this.tempSetting.devId = (evt.getData().get('devId') === undefined ? ' ' : evt.getData().get('devId'))
            if (evt.getData().get('lines') !== undefined && evt.getData().get('lines').length > 0) {
              this.tempSetting.lines = evt.getData().get('lines').join(',')
            } else {
              this.tempSetting.lines = ' '
            }
            if (evt.getData().getStyle(Q.Styles.LABEL_VISIBLE) === undefined) {
              this.tempSetting.showName = 'true'
            } else {
              this.tempSetting.showName = evt.getData().getStyle(Q.Styles.LABEL_VISIBLE) + ''
            }

            if (evt.getData() instanceof Q.Text) {
              // 获取背景颜色
              this.tempSetting.textBgColor = evt.getData().getStyle(Q.Styles.LABEL_BACKGROUND_COLOR) || ''
              this.tempSetting.textColors = evt.getData().getStyle(Q.Styles.LABEL_COLOR) || ''
              this.tempSetting.textBorderColor = evt.getData().getStyle(Q.Styles.LABEL_BORDER_STYLE) || ''
              this.tempSetting.textSize = evt.getData().getStyle(Q.Styles.LABEL_FONT_SIZE) || 10
              // evt.getData().getStyle(Q.Styles.LABEL_BACKGROUND_COLOR) === undefined ? '' :
              this.switches.textDrawer = true
            }
            // 设置图元
            if (evt.getData() instanceof Q.Node && !(evt.getData() instanceof Q.ShapeNode) &&
              !(evt.getData() instanceof Q.Text)) {
              this.tempSetting.size = evt.getData().size.width
              this.setttingModalNode = true
            }
            if (evt.getData() instanceof Q.ShapeNode) {
              this.tempSetting.color = evt.getData().styles['shape.stroke.style']
              this.tempSetting.flowColor = evt.getData().get('color') ? evt.getData().get('color') : ''
              this.tempSetting.width = evt.getData().styles['shape.stroke']
              this.setttingModalLine = true
            }
          }
        }
      }
    },
    methods: {
      getSpaceList: function () {
        this.spaceList2 = this.$store.state.user.spaces[0].children
        this.spaceList = this.$store.state.user.spaces
      },
      addProptype () {
        Q.Graph.prototype.copy = () => {
          let selection = this.graph.selectionModel.toDatas()
          this.CopyElements = selection
        }
        Q.Graph.prototype.paste = (dx, dy) => {
          if (!this.CopyElements) {
            return
          }
          dx = dx || 0
          dy = dy || 0
          let elements = {}// 找出相关的图元，相连的节点，孩子节点，连线的两个端点等
          function addElement (e) {
            if (elements[e.id]) {
              return
            }
            elements[e.id] = e
            if (e.hasChildren()) {
              e.forEachChild(addElement)
            }
            if (e instanceof Q.Edge) {
              addElement(e.from)
              addElement(e.to)
            }
          }

          this.graph.selectionModel.forEach(addElement)

          // 找出所有需要复制的连线，两个端点被选中时，连线也一起复制
          for (let id in elements) {
            let e = elements[id]
            if (e instanceof Q.Node && e.hasEdge()) {
              e.forEachEdge(function (edge) {
                let otherNode = edge.otherNode(e)
                if (otherNode && elements[otherNode.id]) {
                  elements[edge.id] = edge
                }
              })
            }
          }

          console.log('elements', elements)
          let json = this.graph.exportJSON(true, {
            filter: function (e) {
              return e.id in elements
            }
          })

          let clones = this.graph.parseJSON(json)
          // 设置uuid
          clones.forEach(iter => iter.set('did', this.generateUuid(10, 56)))
          console.log('clones', clones)

          clones.forEach(function (clone) {
            if (clone instanceof Q.Node) {
              clone.x = clone.x + dx
              clone.y = clone.y + dy
            }
          })
          // iii
          this.graph.setSelection(clones)
        }
      },
      override (clazz, methodName, overrideMethod) {
        let _super = clazz.prototype[methodName]
        clazz.prototype[methodName] = function () {
          _super.apply(this, arguments)
          return overrideMethod.apply(this, arguments)
        }
      },
      generateBg: function () {
        // 简单生成画板1
        this.graph = new Q.Graph('canvasasd')
        // 禁止双击 放大
        this.graph.enableDoubleClickToOverview = false
        this.graph.editable = true
        // 是否启用右键框选功能
        this.graph.enableRectangleSelectionByRightButton = true
        // 默认的 样式
        this.graph.styles = {}
        this.graph.styles[Q.Styles.EDGE_WIDTH] = 10
        this.graph.styles[Q.Styles.SELECTION_COLOR] = '#0F0'
        this.graph.styles[Q.Styles.ARROW_TO] = null
        // shapeNode 连线默认样式
        this.graph.styles[Q.Styles.SHAPE_STROKE] = 10
        this.graph.styles[Q.Styles.SHAPE_STROKE_STYLE] = '#2898E0'
        // 建立拉线的时候，设置
        // DD
        this.graph.onElementCreated = (element, evt) => {
          if (element instanceof Q.ShapeNode) {
            element.name = ''
            element.set('did', this.generateUuid(10, 56))
            if (this.graph.styles[Q.Styles.SHAPE_STROKE]) {
              element.setStyle(Q.Styles.SHAPE_STROKE, this.graph.styles[Q.Styles.SHAPE_STROKE])
            }
            if (this.graph.styles[Q.Styles.SHAPE_STROKE_STYLE]) {
              element.setStyle(Q.Styles.SHAPE_STROKE_STYLE, this.graph.styles[Q.Styles.SHAPE_STROKE_STYLE])
            }
          }
        }
        // 添加 一些事件
        this.graph.addCustomInteraction(this.events)
        // 重写默认的监听del方法，删除元素
        this.graph.removeSelectionByInteraction = (evt) => {
          this.reWriteRemoveSelectionByInteraction(evt)
        }
        // 添加动画
        this.flowObj = new FlowingSupport(this.graph)
        // 重写监听事件
        this.override(Q.EditInteraction, 'onkeydown', (evt, graph) => {
          let code = evt.keyCode
          if (!Q.isMetaKey(evt)) {
            return
          }
          if (code === 67) {
            graph.copy()
          } else if (code === 86) {
            graph.paste(20, 20)
          } else if (code === 90) {
            // graph.undo()
          } else if (code === 89) {
            // graph.redo()
          } else {
            return
          }
          Q.stopEvent(evt)
        })
      },
      emptyPanel: function () {
        // 清空屏幕
        this.graph.clear()
        // 清空选择的数据
        this.curObj.dids = []
        // 显示数据
        if (this.devs.length !== 0) {
          this.devs.forEach(item => { item.ifShow = true })
        }
      },
      radioChage: function (resp) {
        switch (resp) {
          case '编辑':
            this.graph.interactionMode = Q.Consts.INTERACTION_MODE_DEFAULT
            break
          case '只读':
            this.graph.interactionMode = Q.Consts.INTERACTION_MODE_VIEW
            break
          case '连线':
            this.graph.interactionMode = Q.Consts.INTERACTION_MODE_CREATE_LINE
            break
          default:
            this.graph.interactionMode = Q.Consts.INTERACTION_MODE_DEFAULT
            break
        }
      },
      lineTypeChange: function (type) {
        console.log('Q.Consts.EDGE_TYPE_DEFAULT', type)
        this.graph.edgeType = eval(type)
      },
      addNode: function (item) {
        // 添加节点方法 000
        let node = new Q.Node()
        // 名称
        node.name = item.iotDevType.useType + '(' + item.name + ')'
        // 设置 用户属性，把 设备的id 放进去
        node.set('did', item.id)
        // 随机位置
        node.x = Math.floor(Math.random() * (100))
        node.y = Math.floor(Math.random() * (100))
        // 添加进去
        this.graph.graphModel.add(node)
      },
      addNodeDataHanlder: function (item) {
        //  1.增加 数据处理--- 设备id 放进 系统图对象的 dids 属性中
        this.curObj.dids.push(item.id)
        // 2. 设备选择池 隐藏掉 已经放进去的 设备 ifShow: ---> 已在 上一步 调用 执行隐藏
      },
      initCurObj: function () {
        this.curObj = {
          name: '',
          space: '',
          layoutData: ''
        }
      },
      makeLayoutByJson: function () {
        // todo generate view by code
      },
      generateUuid: function (len, radix) {
        let chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('')
        let uuid = []
        radix = radix || chars.length

        if (len) {
          // Compact form
          for (let i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix]
        } else {
          // rfc4122, version 4 form
          let r

          // rfc4122 requires these characters
          uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-'
          uuid[14] = '4'

          for (let i = 0; i < 36; i++) {
            if (!uuid[i]) {
              r = 0 | Math.random() * 16
              uuid[i] = chars[(i === 19) ? (r & 0x3) | 0x8 : r]
            }
          }
        }
        return uuid.join('')
      },
      addToPool: function (index) {
        this.devs[index].ifShow = false
        // 添加到 系统图 中，调用 添加方法
        this.addNode(this.devs[index])
        // 处理 数据
        this.addNodeDataHanlder(this.devs[index])
      },
      addToPool2: function (imageName) {
        // 添加自定义的 图标 没关联设备的 到显示池
        // let x = 100
        // let y = 100
        let x = Math.floor(Math.random() * (100) + 50)
        let y = Math.floor(Math.random() * (150) + 50)
        let newNoded = this.graph.createNode('', x, y)
        newNoded.image = imageName
        newNoded.size = {width: 100}
        // 是否旋转 Math.PI * 1.5 --- 270    Math.PI  --- 180
        // newNoded.rotate = -Math.PI * 0.5
        // 生成uuid身份11
        newNoded.set('did', this.generateUuid(10, 56))
        // 恢复到 移动模式
        this.model = '编辑'
        this.radioChage('编辑')
      },
      handlerDevDatas: function () {
        // 处理 数据，和 已经在系统图中 数据的 交集关系
        if (this.curObj === null) {
          // 新增的
          if (this.devs.length > 0) {
            this.outPool = this.devs.map(single => single.id)
          }
        }
      },
      exportImage: function () {
        let viewport = this.graph.viewportBounds
        let clip = new Q.Rect(viewport.cx, viewport.cy)
        // 控制 画图的大小，，5 位置越小，图范围越小，反之
        let scall = this.graph.scale / 3
        clip.grow(150 / scall, 350 / scall)
        let imageInfo = this.graph.exportImage(this.graph.scale, clip)
        if (!imageInfo || !imageInfo.data) {
          return false
        }
        let win = window.open()
        let doc = win.document
        doc.title = 'export image - ' + imageInfo.width + ' x ' + imageInfo.height
        let img = doc.createElement('img')
        img.src = imageInfo.data
        doc.body.appendChild(img)
      },
      exportJsons: function () {
        let win = window.open()
        let doc = win.document
        let content = doc.createElement('p')
        content.innerHTML = this.graph.toJSON(true)
        doc.body.appendChild(content)
      },
      importJsons: function () {
        // 导入json数据
        if (!this.doneJson) {
          this.$Message.warning('请输入有效内容.....')
          return
        }
        // 清空布局
        this.graph.clear()
        this.graph.parseJSON(this.doneJson)
        setTimeout(() => { this.doneJson = '' }, 200)
      },
      reWriteRemoveSelectionByInteraction: function (evt) {
        // 重写 RemoveSelectionByInteraction 方法，，变为 中文的提示语！
        let selections = this.graph.selectionModel.datas
        // 获取 设备di  已放在 properties.did 中
        if (!selections || selections.length === 0) {
          return false
        }

        let selection = this.graph.removeSelection()
        if (selection) {
          let event = new Q.InteractionEvent(this, Q.InteractionEvent.ELEMENT_REMOVED, evt, selection)
          this.graph.onInteractionEvent(event)
        }
      },
      saveData: function () {
        // 保存系统图
        if (!this.curObj.name || !this.curObj.space || !this.curObj.energy) {
          this.$Message.info('未完成编辑必要的内容：系统图名称，关联空间，能源类型！')
        } else {
          // 删除流动的ui
          this.stopFlow()
          // 取得画布信息
          let viewport = this.graph.viewportBounds
          let clip = new Q.Rect(viewport.cx, viewport.cy)
          // 控制 画图的大小，，5 位置越小，图范围越小，反之1
          let scall = this.graph.scale / 2
          clip.grow(300 / scall, 450 / scall)
          let imageInfo = this.graph.exportImage(this.graph.scale, clip)
          let formData = new FormData()
          formData.append('img', this.convertBase64UrlToBlob(imageInfo.data))
          this.curObj.layoutData = this.graph.toJSON(true)
          formData.append('sysImg', JSON.stringify(this.curObj))
          this.switches.savingImgStatus = true
          window.myapi.upload('/sysimg/newPic/', formData).then(resp => {
            // this.uploading = false
            if (resp.status === 200 && resp.data.status === 200) {
              this.$Notice.success({
                title: '操作提示',
                desc: '保存成功！返回列表界面 '
              })
            }
          }).catch(info => {
            this.$Notice.warning({
              title: '操作提示',
              desc: info
            })
          }).finally(() => {
            this.switches.savingImgStatus = false
            this.changePanel()
          })
        }
      },
      convertBase64UrlToBlob: function (urlData) {
        let bytes = window.atob(urlData.split(',')[1])
        // 去掉url的头，并转换为byte

        // 处理异常,将ascii码小于0的转换为大于0
        let ab = new ArrayBuffer(bytes.length)
        let ia = new Uint8Array(ab)
        for (let i = 0; i < bytes.length; i++) {
          ia[i] = bytes.charCodeAt(i)
        }

        let blod = new Blob([ab], {type: 'image/png'})
        blod.name = 'sdfaf.png'
        return blod
      },
      maketempSettingDefault () {
        this.tempSetting = {
          color: '',
          flowColor: '',
          devId: '',
          prol: '',
          did: ''
        }
      },
      okNode: function () {
        this.edittingNode.name = this.tempSetting.label
        this.edittingNode.size = {width: this.tempSetting.size}
        this.edittingNode.zIndex = this.tempSetting.zindex
        this.edittingNode.setStyle(Q.Styles.LABEL_VISIBLE, this.tempSetting.showName !== 'false')
        this.edittingNode.set('did', this.tempSetting.did)
        if (this.tempSetting.devId.replace(/\s*/g, '')) {
          this.edittingNode.set('devId', this.tempSetting.devId)
        }
        if (this.tempSetting.prol.replace(/\s*/g, '')) {
          this.edittingNode.set('prol', this.tempSetting.prol)
        }
        if (this.tempSetting.lines.replace(/\s*/g, '')) {
          let arrLines = this.tempSetting.lines.split(',')
          this.edittingNode.set('lines', arrLines)
        }
        // this.maketempSettingDefault()
      },
      okLine: function () {
        this.edittingNode.setStyle(Q.Styles.SHAPE_STROKE, this.tempSetting.width)
        if (this.tempSetting.color !== '') {
          this.edittingNode.setStyle(Q.Styles.SHAPE_STROKE_STYLE, this.tempSetting.color)
        }
        if (this.tempSetting.flowColor !== '') {
          this.edittingNode.set('color', this.tempSetting.flowColor)
        }
        this.edittingNode.name = this.tempSetting.label
        // 取消箭头显示
        this.edittingNode.setStyle(Q.Styles.ARROW_TO, null)
        if (this.tempSetting.zindex) {
          this.edittingNode.zIndex = this.tempSetting.zindex
        }
        /* if (this.tempSetting.ifNarrow === '不显示') {
           this.edittingNode.setStyle(Q.Styles.ARROW_TO, null)
         } else {
           this.edittingNode.setStyle(Q.Styles.ARROW_TO, true)
         } */
        /*   if (this.tempSetting.idDash === '虚线') {
             this.edittingNode.setStyle(Q.Styles.EDGE_LINE_DASH, [8, 4, 0.01, 4])
           } else {
             this.edittingNode.setStyle(Q.Styles.EDGE_LINE_DASH, null)
           } */
        /*    if (this.tempSetting.lineType !== null) {
              this.edittingNode.edgeType = eval(this.tempSetting.lineType)
            } else {
              this.edittingNode.edgeType = Q.Consts.EDGE_TYPE_DEFAULT
            } */
        // this.maketempSettingDefault()
      },
      okText: function () {
        this.edittingNode.name = this.tempSetting.label
        this.edittingNode.zIndex = this.tempSetting.zindex
        this.edittingNode.set('did', this.tempSetting.did)
        if (this.tempSetting.textSize) {
          this.edittingNode.setStyle(Q.Styles.LABEL_FONT_SIZE, this.tempSetting.textSize)
        }
        if (this.tempSetting.textBgColor) {
          this.edittingNode.setStyle(Q.Styles.LABEL_BACKGROUND_COLOR, this.tempSetting.textBgColor)
        }
        if (this.tempSetting.textColors) {
          this.edittingNode.setStyle(Q.Styles.LABEL_COLOR, this.tempSetting.textColors)
        }
        if (this.tempSetting.textBorderColor) {
          this.edittingNode.setStyle(Q.Styles.LABEL_BORDER_STYLE, this.tempSetting.textBorderColor)
        }
        // this.maketempSettingDefault()
      },
      xAline: function () {
        // 使其横对齐
        if (this.graph.selectionModel.length <= 1) {
          this.$Message.info('请至少选择两个图元再进行此操作!')
        } else {
          let standardOne = this.graph.selectionModel.datas[0]
          let standardtTwo = this.graph.selectionModel.datas[1]
          let gap = standardtTwo.x - standardOne.x
          for (let i = 0; i < this.graph.selectionModel.length; i++) {
            let curOne = this.graph.selectionModel.datas[i]
            curOne.y = standardOne.y
            if (i >= 2) {
              // 调节间隔
              let lastOne = this.graph.selectionModel.datas[i - 1]
              curOne.x = lastOne.x + gap
            }
          }
        }
      },
      autoFit: function () {
        this.graph.zoomToOverview()
      },
      stopFlow: function () {
        // 关闭所有流动效果111
        this.flowObj.stop()
      },
      doFlow: function () {
        this.stopFlow()
        // 重新开启流动效果
        this.graph.forEach(item => {
          if (item instanceof Q.ShapeNode) {
            // console.log('item.get', item.get('color'))
            // 添加流动的效果233
            this.flowObj.addFlowing(item, 3, true, item.get('color') ? item.get('color') : '')
          }
        })
        // 执行动态
        this.flowObj.start()
      },
      makeTextNode () {
        let text1 = this.graph.createText('文字', 0, 0)
        text1.setStyle(Q.Styles.LABEL_BORDER, 1)
        text1.setStyle(Q.Styles.LABEL_PADDING, 10)
        text1.setStyle(Q.Styles.LABEL_BORDER_STYLE, '#1D4876') // 边框颜色
        text1.setStyle(Q.Styles.LABEL_BACKGROUND_COLOR, '#1782ff')// 填充颜色
        text1.setStyle(Q.Styles.LABEL_SIZE, new Q.Size(220, 60)) // 长 高ww
        text1.setStyle(Q.Styles.LABEL_COLOR, '#FFF') // 字体颜色1
        text1.size = 150 // 大小33
        text1.set('did', this.generateUuid(10, 56))
      },
      makeBusLine () {
        let bus = new Q.Bus()
        this.graph.addElement(bus)
        bus.moveTo(-200, 0)
        bus.lineTo(200, 0)
        bus.setStyle(Q.Styles.SHAPE_STROKE, 10)
        bus.set('did', this.generateUuid(10, 56))
      },
      makeLanp (x, y, color, message) {
        // 填充颜色
        let lampGradient = new Q.Gradient(Q.Consts.GRADIENT_TYPE_RADIAL,
          [Q.toColor(0xAAFFFFFF), Q.toColor(0x33EEEEEE), Q.toColor(0x44888888), Q.toColor(0x33666666)],
          [0.1, 0.3, 0.7, 0.9], 0, -0.2, -0.2)
        let lamp = this.graph.createNode(message, x, y)
        lamp.image = 'lamp'
        // lamp.name ="总管压力";
        lamp.setStyle(Q.Styles.SHAPE_FILL_COLOR, color)
        lamp.setStyle(Q.Styles.SHAPE_FILL_GRADIENT, lampGradient)
        lamp.setStyle(Q.Styles.SHAPE_STROKE, 0.3)
        lamp.setStyle(Q.Styles.SHAPE_STROKE_STYLE, '#CCC')
        // lamp.setStyle(Q.Styles.LABEL_BACKGROUND_COLOR, '#FF0');
        lamp.setStyle(Q.Styles.LABEL_SIZE, {width: 60, height: 25})
        lamp.setStyle(Q.Styles.SHADOW_OFFSET_X, 0)
        lamp.setStyle(Q.Styles.SHADOW_OFFSET_Y, 0)
        lamp.setStyle(Q.Styles.SHADOW_BLUR, 5)

        return lamp
      },
      wo: function () {
        this.makeLanp(149, 165, '#209120')
        // 隐藏名字name
        /*     this.graph.forEach(item => {
               if (item.name && item.name.indexOf('回水电动阀采集模块') > -1) {
                 item.setStyle(Q.Styles.LABEL_VISIBLE, false)
               }
                }) */

        /*   this.graph.forEach(item => {
              if (item.name.indexOf('#离心机') > -1 || item.name.indexOf('#螺杆机') > -1 || item.name.indexOf('#冷却塔') > -1 ||
                item.name.indexOf('#冷却泵') > -1) {
                  console.log('item', item)
                item.zIndex = 950
              }
            }) */
        /*   this.graph.forEach(item => {
             if (item instanceof Q.ShapeNode) {
               console.log('item', item.bindingUIs.datas)
               let ddd = item.bindingUIs.datas
               for (let i = 0; i < ddd.length; i++) {
                 item.removeUI(ddd[i])
               }
             }
           }) */

        /*     let text1 = this.graph.createText('车间',500,700)
             text1.setStyle(Q.Styles.LABEL_BORDER, 1);
             text1.setStyle(Q.Styles.LABEL_PADDING, 10);
             text1.setStyle(Q.Styles.LABEL_BORDER_STYLE, "#1D4876"); // 边框颜色
             text1.setStyle(Q.Styles.LABEL_BACKGROUND_COLOR, "#FF9999");// 填充颜色
             text1.setStyle(Q.Styles.LABEL_SIZE, new Q.Size(120, 60)); // 长 高
             text1.setStyle(Q.Styles.LABEL_COLOR, "#FFF"); // 字体颜色
             text1.size = 150; // 大小33 */
        /* this.graph.forEach(item => {
             if (item.name && item.name.indexOf('回水电动阀采集模块') > -1) {
                 item.setStyle(Q.Styles.LABEL_VISIBLE, false)
             }
         }) */

        /*     let nodeWithGIF = this.graph.createNode('', 820, -900)
             nodeWithGIF.image = '../../../static/img/chart.svg'
             nodeWithGIF.size = {width: 29}
             nodeWithGIF.setStyle(Q.Styles.BACKGROUND_COLOR, '#1db1e6')
             nodeWithGIF.setStyle(Q.Styles.PADDING, new Q.Insets(10, 10));
             nodeWithGIF.setStyle(Q.Styles.BORDER, 0.5);
             nodeWithGIF.setStyle(Q.Styles.BORDER_COLOR, "#fff");
             nodeWithGIF.setStyle(Q.Styles.BORDER_RADIUS, 0); */

        /* this.graph.forEach(item => {
          if (item instanceof Q.Text && item.name.indexOf('车间') > -1) {
            console.log('dd444d', item)
            item.setStyle(Q.Styles.LABEL_FONT_SIZE, 14)
            item.setStyle(Q.Styles.LABEL_BACKGROUND_GRADIENT, new Q.Gradient(Q.Consts.GRADIENT_TYPE_LINEAR,
              ['#1db1e6', '#1ea6e6'], null, Math.PI / 2))
            item.zIndex = 1222
          }
        }) */

        // let line11 = this.createText(null, '总的气量', 830, -900, null, 50, 30, 20, '#434343', '#CAD0DF')
        // let line12 = this.createText(null, '454545434345.99', 930, -900, null, 180, 30, 20, '#434343', '#CAD0DF')
        // let line13 = this.createText(null, 'min/m³', 1160, -900, null, 80, 30, 20, '#434343', '#CAD0DF')

        // let line21 = this.createText(null, '瞬时流量', 830, -870, null, 50, 30, 20, '#434343', '#CAD0DF')
        // let line22 = this.createText(null, '454545434345.99', 870, -900, null, 220, 30, 20, '#434343', '#CAD0DF')
        // let line23 = this.createText(null, 'min/m³', 1160, -870, null, 80, 30, 20, '#CAD0DF', '#CAD0DF')
        //
        // let line31 = this.createText(null, '单气效率', 830, -870, null, 50, 30, 20, '#434343', '#CAD0DF')
        // let line32 = this.createText(null, '454545434345.99', 870, -900, null, 220, 30, 20, '#434343', '#CAD0DF')
        // let line33 = this.createText(null, 'min/m³', 1160, -870, null, 80, 30, 20, '#CAD0DF', '#CAD0DF')
      },
      createText (host, name, x, y, anchorPosition, w, h, fontSize, fontColor, backgroundColor) {
        let text = this.graph.createText(name, x, y)
        text.setStyle(Q.Styles.LABEL_BORDER, 0.5)
        text.setStyle(Q.Styles.LABEL_RADIUS, 0)
        text.setStyle(Q.Styles.LABEL_PADDING, 10)
        text.setStyle(Q.Styles.LABEL_BORDER_STYLE, '#ffffff')
        if (host) {
          text.host = text.parent = host
        }
        if (anchorPosition) {
          text.anchorPosition = anchorPosition
          text.setStyle(Q.Styles.LABEL_ALIGN_POSITION, anchorPosition)
        }
        if (w && h) {
          text.setStyle(Q.Styles.LABEL_SIZE, new Q.Size(w, h))
        }

        text.setStyle(Q.Styles.LABEL_FONT_SIZE, fontSize || 14)
        text.setStyle(Q.Styles.LABEL_COLOR, fontColor || '#555')
        text.setStyle(Q.Styles.LABEL_BACKGROUND_COLOR, backgroundColor || null)
        text.setStyle(Q.Styles.LABEL_BACKGROUND_GRADIENT, new Q.Gradient(Q.Consts.GRADIENT_TYPE_LINEAR,
          ['#1db1e6', '#1ea6e6'], null, Math.PI / 2))
        return text
      },
      yAline: function () {
        // 使其竖对齐
        if (this.graph.selectionModel.length <= 1) {
          this.$Message.info('请至少选择两个图元再进行此操作!')
        } else {
          let standardOne = this.graph.selectionModel.datas[0]
          let standardtTwo = this.graph.selectionModel.datas[1]
          let gap = standardtTwo.y - standardOne.y
          for (let i = 0; i < this.graph.selectionModel.length; i++) {
            let curOne = this.graph.selectionModel.datas[i]
            curOne.x = standardOne.x
            if (i >= 2) {
              // 调节间隔
              let lastOne = this.graph.selectionModel.datas[i - 1]
              curOne.y = lastOne.y + gap
            }
          }
        }
      },
      delPic: function () {
        // 删除系统图
        if (this.curObj.id) {
          let config = {
            title: '删除系统图',
            content: '您确定删除吗该系统图吗？',
            onOk: () => {
              this.switches.delImgStatus = true
              window.myapi.do_del('sysimg/del', [this.curObj.id]).then(resp => {
                if (resp.status === 200 && resp.data.status === 200) {
                  this.$Notice.success({
                    title: '提示',
                    desc: '删除成功，返回选择列表!'
                  })
                  this.changePanel()
                } else {
                  this.$Notice.error({
                    title: '提示',
                    desc: resp.data.msg
                  })
                }
              }).catch(reason => {
                this.$Notice.warning({
                  title: '提示',
                  desc: '删除出错，请检查.......'})
              }).finally(() => {
                this.switches.delImgStatus = false
              })
            }
          }
          this.$Modal.confirm(config)
        } else {
          this.$Message.info('系统图不存在，无需删除.......')
        }
      },
      cancel: function () {
        // this.tempSetting = {}
      },
      modalVisible: function (resps) {
        if (!resps) {
          this.edittingNode = null
          this.maketempSettingDefault()
          this.doneJson = ''
        }
      },
      drawerChange: function (status) {
        if (status) {
          this.expertEditJson = this.graph.toJSON(true)
        }
      },
      textDrawerChange: function (status) {
        if (!status) {

        }
      },
      changePanel: function () {
        // 清空
        this.ifEditStatus = false
        this.graph.clear()
        // 调用 子组件 的刷新数据 方法
        this.$refs.listPanel.loadImgsData()
        // 清空 curObj对象
        this.curObj = {}
        this.devs = []
        this.factName = []
        // 停止流动
        this.stopFlow()
      },
      tellEdit: function (data) {
        // 跳转到 编辑 界面
        if (data === null) {
          this.initCurObj()
        } else {
          this.curObj = data
        }
        // 编辑系统图
        this.graph.clear()
        // 显示编辑板块
        this.ifEditStatus = true
        // 恢复 编辑模式为 移动模式
        this.model = '编辑'
        // 延迟加载  避免qunee 获取不到父级的长宽
        setTimeout(() => {
          if (data !== null) {
            // 把json 数据转为 视图的方法
            this.graph.parseJSON(data.layoutData)
          }
          // 刷新视图
          this.graph.updateViewport()
          // 移到中心显示
          this.graph.moveToCenter()
        }, 100)
      }
    }
  }

</script>
<style lang="less">
  .vertical-center-modal {
    justify-content: center;

    .ivu-modal {
      float: right;
      margin-right: 100px;
      margin-top: 50px;
    }
  }

  .fatherToolBar {
    margin-bottom: 10px;
    border-bottom: solid #e4e0e0 1px;
    padding-bottom: 5px;
  }
  .editPanel {
  }
  .selectPanel {
    height: 800px;
    /*border: 1px solid #ded9d9;*/
  }

  .cann{
    height: 1000px;
    border: 1px solid #ded9d9;
    background: #EEE;
  }
  .ddz2 {
    display: flex;
  }
  .ddz21 {
    display: flex;
    width: 100%;
  }

  .ddz3 {
    flex: 1;
  }

  .ddx8 {
    flex: 0 0 50px;
    line-height: 32px;
    text-align: right;
    padding-right: 10px;
  }
  .ddx08 {
    flex: 0 0 80px;
    line-height: 32px;
    text-align: right;
    padding-right: 10px;
  }

  .ddx9 {
    flex: 0 0 50px;
    line-height: 32px;
    text-align: right;
    padding-right: 10px;
  }

  .devBg{
    border: solid 1px #e7e2e2;
    padding: 3px;
    /* background: #f9f9f9; */
    border-radius: 5px;
    margin: 3px;
  }

  .devBB{
    height: 40%;
    width: 100%;
    padding-left: 10px;
    overflow-y: scroll;
  }
  .devBBC{
    height: 40%;
    width: 100%;
    padding-left: 10px;
    padding-top: 20px;
    overflow-y: scroll;
  }
  .devBBCD{
    height: 20%;
    width: 100%;
    padding-left: 10px;
    padding-top: 20px;
    overflow-y: scroll;
  }
  .devBBT1{
    font-size: 14px;
    border-bottom: solid 1px #dcdada;
    margin-left: 10px;
  }
  .devBBT{
    font-size: 14px;
    padding: 7px 0px 2px;
    border-bottom: solid 1px #dcdada;
  }
  .mainBgg{
    display: flex;
    height: 1000px;
    padding: 8px 5px;
  }
</style>
